/*
 * Copyright 2014-2026 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.wzq.framework.util;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.Pipeline;

/**
 * @author <a href="mailto:yanghao@0easy.com">杨浩</a>
 */
public class UtilJedis {

	public static boolean exists(JedisPool pool, String key) {
		try (Jedis jedis = pool.getResource()) {
			return jedis.exists(key);
		}
	}
	
	//string start
	public static String get(JedisPool pool, String key) {
		try (Jedis jedis = pool.getResource()) {
			return jedis.get(key);
		}
	}
	public static boolean setex(JedisPool pool, String key, int seconds, Object value) {
		String json = UtilJson.writeValueAsString(value);
		try (Jedis jedis = pool.getResource()) {
			return "OK".equalsIgnoreCase(jedis.setex(key, seconds, json));
		}
	}
	/** 先判断key是否存在，不存在就设置，否则不操作(true=不存在 且 设置成功) */
	public static boolean setnex(JedisPool pool, String key, int seconds, Object value) {
		String json = UtilJson.writeValueAsString(value);
		try (Jedis jedis = pool.getResource()) {
			if (!jedis.exists(key)) return "OK".equalsIgnoreCase(jedis.setex(key, seconds, json));
		}
		return false;
	}
	//string end

	
	public static Set<String> hkeys(JedisPool pool, String key) {
		try (Jedis jedis = pool.getResource()) {
			return jedis.hkeys(key);
		}
	}
	/** 如果不存在就创建hash，并设定过期时间，__t存储的是创建时间 */
	private static void createHashForExpireNx(Jedis jedis, String mapkey, int seconds) {
		if (!jedis.exists(mapkey)) {
			Pipeline line = jedis.pipelined();
			line.hsetnx(mapkey, "__t", UtilDate.format(new Date()));
			line.expire(mapkey, seconds);
			line.sync();
		}
	}
	/**
	 * 如果不存在就创建hash，并设定过期时间，__t存储的是创建时间
	 */
	public static void createHashForExpireNx(JedisPool pool, String mapkey, int seconds) {
		try (Jedis jedis = pool.getResource()) {
			createHashForExpireNx(jedis, mapkey, seconds);
		}
	}
	/** 如果hash不存在，创建，并设定seconds后过期 */
	public static <K> void hmset(JedisPool pool, String mapkey, Map<K, String> map, int seconds) {
		Map<String, String> hash = new HashMap<>();
		for (Entry<K, String> entry : map.entrySet()) {
			hash.put(UtilString.toString(entry.getKey()), entry.getValue());
		}
		try (Jedis jedis = pool.getResource()) {
			createHashForExpireNx(jedis, mapkey, seconds);
			if (!map.isEmpty()) jedis.hmset(mapkey, hash);
		}
	}
	/** key=__开始的是内部变量，请忽略 */
	public static Map<String, String> hgetall(JedisPool pool, String mapkey) {
		try (Jedis jedis = pool.getResource()) {
			return jedis.hgetAll(mapkey);
		}
	}
	/** 如果map不存在返回size=0的map */
	@SuppressWarnings("unchecked")
	public static <K> Map<K, String> hmget0(JedisPool pool, String mapkey, Collection<K> fields) {
		Map<K, Integer> keysMap = new HashMap<>();
		List<String> keys = new ArrayList<>();
		for (K field : new HashSet<>(fields)) {
			keysMap.put(field, keys.size());
			keys.add(UtilString.toString(field));
		}
		
		List<Object> all;
		try (Jedis jedis = pool.getResource()) {
			Pipeline pipeline = jedis.pipelined();
			pipeline.exists(mapkey);
			pipeline.hmget(mapkey, keys.toArray(new String[0]));
			all = pipeline.syncAndReturnAll();
		}
		
		Map<K, String> result = new LinkedHashMap<>();
		if (!Boolean.TRUE.equals(all.get(0))) return result;
		
		List<String> values = (List<String>) all.get(1);
		for (Entry<K, Integer> entry : keysMap.entrySet()) {
			result.put(entry.getKey(), values.get(entry.getValue()));
		}
		return result;
	}
	/** 无论map是否存在都返回包含fields的map */
	public static <K> Map<K, String> hmget(JedisPool pool, String mapkey, Collection<K> fields) {
		Map<K, Integer> keysMap = new HashMap<>();
		List<String> keys = new ArrayList<>();
		for (K field : new HashSet<>(fields)) {
			keysMap.put(field, keys.size());
			keys.add(UtilString.toString(field));
		}
		
		List<String> values;
		try (Jedis jedis = pool.getResource()) {
			values = jedis.hmget(mapkey, keys.toArray(new String[0]));
		}
		
		Map<K, String> result = new LinkedHashMap<>();
		for (Entry<K, Integer> entry : keysMap.entrySet()) {
			result.put(entry.getKey(), values.get(entry.getValue()));
		}
		return result;
	}
	public static void hmset(JedisPool pool, String mapkey, Map<String, String> map) {
		if (map.isEmpty()) return;
		
		try (Jedis jedis = pool.getResource()) {
			jedis.hmset(mapkey, map);
		}
	}
	public static long hincrby(JedisPool pool, String key, String field, long value) {
		try (Jedis jedis = pool.getResource()) {
			return jedis.hincrBy(key, field, value);
		}
	}
	public static boolean hexists(JedisPool pool, String key, String field) {
		try (Jedis jedis = pool.getResource()) {
			return jedis.hexists(key, field);
		}
	}

	/** 1执行成功， 0 如果给定的域已经存在，且没有操作被执行 */
	public static int hsetnx(JedisPool pool,  String key, String field, String value) { 
		try (Jedis jedis = pool.getResource()) {
			return jedis.hsetnx(key, field, value).intValue();
		}
	}
}
